package com.xhh.adjust.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.utils.thread.ThreadLocalUtil;
import com.xhh.adjust.mapper.AdjustMapper;
import com.xhh.adjust.service.AdjustService;
import com.xhh.apis.adjust.IAdjustClient;
import com.xhh.apis.check.ICheckClient;
import com.xhh.apis.user.IUserClient;
import com.xhh.common.constants.AdjustConstants;
import com.xhh.common.constants.CheckedConstants;
import com.xhh.model.adjust.dtos.AddAdjustDto;
import com.xhh.model.adjust.dtos.AdjustPageDto;
import com.xhh.model.adjust.dtos.AdjustUpdateDto;
import com.xhh.model.adjust.dtos.GetAdjustDto;
import com.xhh.model.adjust.pojos.Adjustment;
import com.xhh.model.adjust.pojos.Faulty;
import com.xhh.model.adjust.pojos.Major;
import com.xhh.model.check.pojos.Unity;
import com.xhh.model.check.vos.CheckedVo;
import com.xhh.model.common.dtos.PageResponseResult;
import com.xhh.model.common.dtos.ResponseResult;
import com.xhh.model.common.enums.AppHttpCodeEnum;
import com.xhh.model.user.pojos.School;
import com.xhh.model.user.pojos.User;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
@RequiredArgsConstructor
public class AdjustServiceImpl extends ServiceImpl<AdjustMapper, Adjustment> implements AdjustService {

    private final ICheckClient checkClient;
    private final IAdjustClient adjustClient;

    /**
     * 新增缺额信息
     * @param addAdjustDto
     * @return
     */
    @Override
    public ResponseResult addAdjustment(AddAdjustDto addAdjustDto) {
        // 1. 校验参数
        if (addAdjustDto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 2. 添加数据
        // 2.1 准备数据
        Adjustment adjustment = BeanUtil.copyProperties(addAdjustDto, Adjustment.class);
//        // 获取登录用户的id
         User user = ThreadLocalUtil.getUser();
        // 根据单位id获取单位编码
        ResponseResult result = checkClient.getUnityById(addAdjustDto.getUnityId());
        String json = JSON.toJSONString(result.getData());
        Unity unity = JSONObject.parseObject(json, Unity.class);
        // 根据院系编码获取院系名称
        Faulty faulty = getFauByCode(addAdjustDto.getFaultyCode());
        // 根据专业编码获取专业名称
        Major major = getMajorByCode(addAdjustDto.getMajorCode());
        // 补充参数
        adjustment.setUserId(user.getId());
        if (StrUtil.isNotEmpty(addAdjustDto.getStatus())) {
            adjustment.setStatus(addAdjustDto.getStatus());
        } else {
            adjustment.setStatus(AdjustConstants.NOT_REPUBLISH);
        }
        adjustment.setUnityCode(unity.getUnityCode());
        adjustment.setFaultyName(faulty.getFaultyName());
        adjustment.setMajorName(major.getMajorName());
        adjustment.setCreateTime(new Date());
        adjustment.setUpdateTime(new Date());
        // 2.2 添加
        save(adjustment);
        // 3. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 分页查询缺额信息
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getAdjustmentByPage(AdjustPageDto dto) {
        // 1. 分页参数校验
        dto.checkParam();
        // 2. 分页查询
        // 2.1 获取登录用户的id
        User user = ThreadLocalUtil.getUser();
        Long userId = user.getId();
        ResponseResult response = checkClient.checkIdentity(userId);
        String json = (String) response.getData();
        CheckedVo checked = JSONObject.parseObject(json, CheckedVo.class);
        // 2.2 查询
        Page<Adjustment> page = new Page<>(dto.getPage(), dto.getSize());
        // 学生
        if (checked.getIdentityCode().equals(CheckedConstants.STUDENT_IDENTITY_CODE)) {
            page = lambdaQuery()
                    .eq(StrUtil.isNotEmpty(dto.getUnityCode()), Adjustment::getUnityCode, dto.getUnityCode())
                    .eq(StrUtil.isNotEmpty(dto.getMajorCode()), Adjustment::getMajorCode, dto.getMajorCode())
                    .eq(dto.getCount() != null, Adjustment::getCount, dto.getCount())
                    // 状态码501 对学生不可见
                    .ne(Adjustment::getStatus, AdjustConstants.NOT_REPUBLISH)
                    .orderByDesc(Adjustment::getUpdateTime)
                    .page(page);
            // 处理数据 如果状态码为502，则学生用户不能查看缺额人数
            List<Adjustment> records = page.getRecords();
            for (Adjustment record : records) {
                if (record.getStatus().equals(AdjustConstants.NOT_REPUBLISH_COUNT)) {
                    record.setCount(null);
                }
            }

        }
        // 招生单位
        if (checked.getIdentityCode().equals(CheckedConstants.SCHOOL_IDENTITY_CODE)) {
            page = lambdaQuery()
                    .eq(Adjustment::getUserId, userId)
                    .eq(StrUtil.isNotEmpty(dto.getFaultyCode()), Adjustment::getFaultyCode, dto.getFaultyCode())
                    .eq(StrUtil.isNotEmpty(dto.getStatus()), Adjustment::getStatus, dto.getStatus())
                    .orderByDesc(Adjustment::getUpdateTime)
                    .page(page);
        }
        // 3. 返回结果
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        responseResult.setData(page.getRecords());
        return responseResult;
    }

    /**
     * 根据id更新缺额信息
     * @param dto
     * @return
     */
    @Override
    public ResponseResult updateAdjustment(AdjustUpdateDto dto) {
        // 1. 校验参数
        if (dto.getId() == null || StrUtil.isBlank(dto.getUnityCode())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 2. 更新数据
        boolean update = lambdaUpdate()
                .set(dto.getStatus() != null, Adjustment::getStatus, dto.getStatus())
                .set(dto.getCount() != null, Adjustment::getCount, dto.getCount())
                .set(dto.getDemand() != null, Adjustment::getDemand, dto.getDemand())
                .set(Adjustment::getUpdateTime, new Date())
                .eq(Adjustment::getId, dto.getId())
                .eq(Adjustment::getUnityCode, dto.getUnityCode())
                .update();
        if (!update) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
        // 3. 返回结果
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 根据单位编码、院系编码、专业编码查询缺额信息
     * @param dto
     * @return
     */
    @Override
    public ResponseResult getAdjustByCode(GetAdjustDto dto) {
        // 1. 校验参数
        if (dto.getUnityCode() == null || dto.getFaultyCode() == null || dto.getMajorCode() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        // 2. 构建插叙条件
        Adjustment adjustment = lambdaQuery()
                .eq(Adjustment::getUnityCode, dto.getUnityCode())
                .eq(Adjustment::getFaultyCode, dto.getFaultyCode())
                .eq(Adjustment::getMajorCode, dto.getMajorCode())
                .ne(Adjustment::getStatus, AdjustConstants.NOT_REPUBLISH)
                .one();
        if (adjustment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        // 3. 返回结果
        return ResponseResult.okResult(adjustment);
    }

    /**
     * 根据院系编码获取院系名称
     * @param faultyCode
     * @return
     */
    private Faulty getFauByCode(String faultyCode) {
        ResponseResult responseResult = adjustClient.getFaultyByCode(faultyCode);
        String fauStr = JSON.toJSONString(responseResult.getData());
        return JSONObject.parseObject(fauStr, Faulty.class);
    }

    /**
     * 根据专业编码获取专业信息
     * @param majorCode
     * @return
     */
    private Major getMajorByCode(String majorCode) {
        ResponseResult responseResult = adjustClient.getMajorByCode(majorCode);
        String fauStr = JSON.toJSONString(responseResult.getData());
        return JSONObject.parseObject(fauStr, Major.class);
    }
}
